package mowbot.serial;

import java.io.InputStream;
import java.io.OutputStream;
import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;
import java.util.Enumeration;
import mowbot.CommonInterface;

public class SerialInterface extends CommonInterface implements SerialPortEventListener {
	SerialPort serialPort;
        /** The port we're normally going to use. */
	private static final String PORT_NAMES[] = {
                        "COM1",
                        "COM2",
			"COM3", // Windows
                        "COM4",
                        "COM5",
                        "COM6"
			};
	/** Buffered input stream from the port */
	private InputStream input;
	/** The output stream to the port */
	private OutputStream output;
	/** Milliseconds to block while waiting for port open */
	private static final int TIME_OUT = 2000;
	/** Default bits per second for COM port. */
	private static final int DATA_RATE = 9600;


        private boolean disable_;
	public void initialize(boolean disable) {
                disable_ = disable;

                if(!disable)
                {
                    CommPortIdentifier portId = null;
                    Enumeration portEnum = CommPortIdentifier.getPortIdentifiers();

                    // iterate through, looking for the port
                    while (portEnum.hasMoreElements()) {
                            CommPortIdentifier currPortId = (CommPortIdentifier) portEnum.nextElement();
                            for (String portName : PORT_NAMES) {
                                    if (currPortId.getName().equals(portName)) {
                                            portId = currPortId;
                                            break;
                                    }
                            }
                    }

                    if (portId == null) {
                            System.out.println("Could not find COM port.");
                            return;
                    }

                    try {
                            // open serial port, and use class name for the appName.
                            serialPort = (SerialPort) portId.open(this.getClass().getName(),
                                            TIME_OUT);

                            // set port parameters
                            serialPort.setSerialPortParams(DATA_RATE,
                                            SerialPort.DATABITS_8,
                                            SerialPort.STOPBITS_1,
                                            SerialPort.PARITY_NONE);

                            // open the streams
                            input = serialPort.getInputStream();
                            output = serialPort.getOutputStream();

                            // add event listeners
                            serialPort.addEventListener(this);
                            serialPort.notifyOnDataAvailable(true);
                    } catch (Exception e) {
                            System.err.println(e.toString());
                    }
            }
	}

	/**
	 * This should be called when you stop using the port.
	 * This will prevent port locking on platforms like Linux.
	 */
	public synchronized void close() {
            if(disable_)
                return;


		if (serialPort != null) {
			serialPort.removeEventListener();
			serialPort.close();
		}
	}

	/**
	 * Handle an event on the serial port. Read the data and print it.
	 */
	public synchronized void serialEvent(SerialPortEvent oEvent) {
            if(disable_) return;
            
		if (oEvent.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
			try {
				int available = input.available();
				byte chunk[] = new byte[available];
				input.read(chunk, 0, available);
                                 
				// Displayed results are codepage dependent
				System.out.print(new String(chunk));
			} catch (Exception e) {
				System.err.println(e.toString());
			}
		}
		// Ignore all the other eventTypes, but you should consider the other ones.
	}

        @Override
        public synchronized void writeData(String data){
            if(disable_) return;

            try {
                output.write(data.getBytes());
            } catch (Exception e) {
		System.err.println(e.toString());
           }
       }

}
